package com.lilanz.facepass.config;

import com.alibaba.fastjson.JSON;
import com.lilanz.facepass.entity.log.Log;
import com.lilanz.facepass.service.impl.LogServiceImpl;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

/**
 * @ Author     ：熊荣健
 * @ Date       ：Created in 2018.10.14
 * @ Description：全局日志统一获取
 * @ Modified By：
 * @Version:
 */
@Aspect
@Component//将这个类引入spring容器中去
public class WebLogAspect {
    @Resource
    LogServiceImpl logService;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    //要处理的方法，包名+类名+方法名  要注意子包在子包等要多加个*
    @Pointcut("execution(public * com.lilanz.facepass.controller.*.*.*(..))")
    public void cut() {
    }

    @Before("cut()")//在调用上面 @Pointcut标注的方法前执行以下方法
    public void doBefore(JoinPoint joinPoint) throws Throwable {//用于获取类方法
    }

    @After("cut()")//无论Controller中调用方法以何种方式结束，都会执行
    public void doAfter() throws Throwable {
    }

    @AfterReturning(returning = "obj", pointcut = "cut()")//在调用上面 @Pointcut标注的方法后执行。用于获取返回值
    public void doAfterReturning(JoinPoint joinPoint, Object obj) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Log log = new Log();
        logger.info("《===============================开始记录=====================================》");

        //时间
        log.setCreateTime(new Date());
        logger.info("时间：" + new Date());

        //uri
        log.setUri(request.getRequestURI());
        logger.info("请求的接口 ：" + request.getRequestURI());

        //ip
        log.setIp(request.getRemoteAddr());
        logger.info("用户IP ： " + request.getRemoteAddr());

        //参数
        String params = getParams(joinPoint, request);
        logger.info("入参:  " + params);
        log.setInsertMessage(params);

        if (obj != null) {
            log.setReturnMessage(obj.toString());
            logger.info("返回给用户的结果 : " + obj.toString());
        }
        logger.info("《===============================结束记录=====================================》");
        logService.insertLog(log);
    }


    /**
     * 请求参数拼装
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        StringBuilder params = new StringBuilder();
        if (paramsArray != null && paramsArray.length > 0) {
            for (Object aParamsArray : paramsArray) {
                String jsonObj = JSON.toJSONString(aParamsArray);
                params.append(jsonObj).append(" ");
            }
        }
        return params.toString().trim();
    }


    @AfterThrowing(pointcut = "cut()", throwing = "e")//切点在cut()
    public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获
        Log log = new Log();
        logger.error("《=============报错了==================以下是报错信息，开始记录=====================================》");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //时间
        log.setCreateTime(new Date());
        logger.error("时间：" + new Date());

        //uri
        log.setUri(request.getRequestURI());
        logger.error("请求的接口 ：" + request.getRequestURI());

        //ip
        log.setIp(request.getRemoteAddr());
        logger.error("用户IP: " + request.getRemoteAddr());

        //参数
        String params = getParams(joinPoint, request);
        logger.error("入参:  " + params);
        log.setInsertMessage(params);

        String errorMessage = "错误信息: " + e.getMessage() + " 错误的接口: " + request.getRequestURL();
        logger.error(errorMessage);

        log.setErrorMessage(errorMessage);

        logger.error("《==============报错了================以下是报错信息，结束记录=====================================》");
        logService.insertLog(log);


    }

    private String getParams(JoinPoint joinPoint, HttpServletRequest request) {
        String params;
        if ("POST".equals(request.getMethod())) {
            Object[] paramsArray = joinPoint.getArgs();

            params = argsArrayToString(paramsArray);
        } else {
            Map<?, ?> paramsMap = (Map<?, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            params = paramsMap.toString();
        }
        return params;
    }


}
